﻿#include"SessionMgr.hpp"
#include"../Base/Network/Session.hpp"
#include<iostream>



namespace SC_SUN
{

    SessionMgr::SessionMgr()
        : mOnlyOnePerType(false)
    {
        mSessionAddedCallback = [this](const auto&){};
        mSssionDeleteCallback = [this](const auto&){};
        mSessionTypedCallback = [this](const auto& , int){};
        mSessionDeTypedCallback = [this](const auto&, int){};
    }

    SessionMgr::~SessionMgr()
    {
    }

    void SessionMgr::OnlyOnePerType()
    {
        mOnlyOnePerType = true;
    }

    bool SessionMgr::AddSession(const std::shared_ptr<MMFNetwork::Session>& session)
    {
        MMF::LockGuard lk(mMutex);

        //查找，这里不多可以直接这样写
        bool flag = false;
        for (size_t i = 0; i < mSessions.size(); i++)
        {
            if (mSessions[i] == session)
            {
                flag = true;
                break;
            }
        }

        //删除并执行回调函数
        mSessions.push_back(session);
        mSessionAddedCallback(session);

        return true;
    }

    bool SessionMgr::DelSession(const std::shared_ptr<MMFNetwork::Session>& session)
    {
        MMF::LockGuard lk(mMutex);
        
        //查找，这里不多可以直接这样写
        size_t idx = -1;
        for (size_t i = 0; i < mSessions.size(); i++)
        {
            if (mSessions[i] == session)
            {
                idx = i;
                break;
            }
        }

        if (idx < 0)
            return false;

        //删除类型映射
        std::unordered_map<std::shared_ptr<MMFNetwork::Session>, int>::iterator typeIt = mSessionsToType.find(mSessions[idx]);
        if (typeIt != mSessionsToType.end())
        {
            mTypeToSessions.erase(typeIt->second);
            mSessionsToType.erase(typeIt);
        }

        //删除并执行回调函数
        mSessions.erase(mSessions.begin() + idx);
        mSssionDeleteCallback(session);

        return true;
    }

    bool SessionMgr::Type(int type, const std::shared_ptr<MMFNetwork::Session>& session)
    {
        MMF::LockGuard lk(mMutex);

        //查找，这里不多可以直接这样写
        bool flag = false;
        for (size_t i = 0; i < mSessions.size(); i++)
        {
            if (mSessions[i] == session)
            {
                flag = true;
                break;
            }
        }
        if (!flag)
            return false;

        //查找分类
        std::unordered_map<int, std::unordered_set<std::shared_ptr<MMFNetwork::Session>>>::iterator it = mTypeToSessions.find(type);

        //当只允许每个类型一个用户的时候
        if (
            mOnlyOnePerType && 
            it != mTypeToSessions.end() &&
            mTypeToSessions.size() != 0
            )
            return false;

        if (it == mTypeToSessions.end())  //没有找到分类
        {
            std::unordered_set<std::shared_ptr<MMFNetwork::Session>> sets = {session};
            mTypeToSessions.emplace(type, sets);
            mSessionsToType.emplace(session, type);
        }
        else                        //找到了
        {
            std::unordered_set<std::shared_ptr<MMFNetwork::Session>>& sets = it->second;
            if (sets.find(session) != sets.end())   //找到同样的了
                return false;
            sets.emplace(session);
            mSessionsToType.emplace(session, type);
        }

        //执行回调函数
        mSessionTypedCallback(session, type);
        
        return true;
    }

    void SessionMgr::DeType(int type, const std::shared_ptr<MMFNetwork::Session>& session)
    {
        MMF::LockGuard lk(mMutex);
        if (mSessionsToType.find(session) == mSessionsToType.end())
            return;

        std::unordered_set<std::shared_ptr<MMFNetwork::Session>>& sessions = mTypeToSessions[type];
        sessions.erase(session);
        mSessionsToType.erase(session);

        //执行回调函数
        mSessionDeTypedCallback(session, type);
    }

    void SessionMgr::DeType(const std::shared_ptr<MMFNetwork::Session>& session)
    {
        MMF::LockGuard lk(mMutex);

        if (mSessionsToType.find(session) == mSessionsToType.end())
            return;

        int type = mSessionsToType[session];
        DeType(type, session);
    }

    void SessionMgr::SendToAll(void* msg, uint32_t msgLen)
    {
        MMF::LockGuard lk(mMutex);
        for (auto& pair: mTypeToSessions)
        {
            for (auto& inPair: pair.second)
                inPair->Send(msg, msgLen);
        }
    }

    void SessionMgr::AsyncSendToAll(void* msg, uint32_t msgLen)
    {
        MMF::LockGuard lk(mMutex);
        for (auto& pair: mTypeToSessions)
        {
            for (auto& inPair: pair.second)
                inPair->AsyncSend(msg, msgLen);
        }
    }

    void SessionMgr::SetSessionAddedCallback(std::function<void(const std::shared_ptr<MMFNetwork::Session>&)> handler)
    {
        mSessionAddedCallback = handler;
    }

    void SessionMgr::SetSessionDeleteCallback(std::function<void(const std::shared_ptr<MMFNetwork::Session>&)> handler)
    {
        mSssionDeleteCallback = handler;
    }

    void SessionMgr::SetSessionTypedCallback(std::function<void(const std::shared_ptr<MMFNetwork::Session>&, int)> handler)
    {
        mSessionTypedCallback = handler;
    }

    void SessionMgr::SetSessionDeTypedCallback(std::function<void(const std::shared_ptr<MMFNetwork::Session>&, int)> handler)
    {
        mSessionDeTypedCallback = handler;
    }
}